﻿#region Using directives

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

using System.Windows.Forms;

#endregion

namespace Weazel.Toad.Application.Actions
{
  public abstract class ActionBase
  {
    public event EventHandler<EventArgs> EnabledChanged;

    private static readonly Dictionary<Type, ActionBase> actions = new Dictionary<Type,ActionBase>();
    
    /// <summary>
    /// Contains all registed actions keyed
    /// by their respective type.
    /// </summary>
    /// <example>ActionBase.Actions[typeof(MyAction)].Execute(this, EventArgs.Empty);</example>
    /// <value></value>
    public static Dictionary<Type, ActionBase> Actions
    {
      get { return actions; }
    }

    /// <summary>
    /// The list of <see cref="ToolStripMenuItem"/>'s bound
    /// to this action.
    /// </summary>
    protected readonly List<ToolStripItem> boundItems = new List<ToolStripItem>();

    private bool enabled = true;
    
    /// <summary>
    /// True iff this action is enabled and
    /// false otherwise. Actions are enabled
    /// by default.
    /// </summary>
    /// <value></value>
    public bool Enabled
    {
      get { return enabled; }
      set {
        if (enabled != value)
        {
          enabled = value;
          if (EnabledChanged != null)
          {
            EnabledChanged(this, EventArgs.Empty);
          }

          // flip settings on all bound items
          foreach (ToolStripItem item in boundItems)
          {
            item.Enabled = enabled;
          }
        }
      }
    }

    private bool @checked;

    /// <summary>
    /// TODO: missing comment peter ;)
    /// </summary>
    /// <value></value>
    public bool Checked
    {
      get { return @checked; }
      set
      {
        if (@checked != value)
        {
          @checked = value;

          foreach(ToolStripItem item in boundItems)
            if(item is ToolStripButton)
              ((ToolStripButton)item).Checked = @checked;
        }
      }
    }

		/// <summary>
		/// Set the text of all items bound to this action
		/// </summary>
		/// <param name="text"></param>
		public void SetTextOfToolStipItems(string text)
		{
			foreach (ToolStripItem item in boundItems)
				item.Text = text;
		}

		/// <summary>
		/// Called when a new item is bound
		/// </summary>
		/// <param name="item">Bound item</param>
		protected virtual void OnItemBound(ToolStripItem item)
		{
			// intentionally left empty
		}

    /// <summary>
    /// Register actions, this could also be
    /// automated and would be less error prone, 
    /// but on the other hand hurt startup time 
    /// and action-dependency issues.
    /// 
    /// Called in Application.Instance() method
    /// since GUI must be fully initialized such
    /// that actions can bind event handlers.
    /// </summary>
    public static void RegisterActions()
    {
      //
      // register actions below...
      //

      addAction(new NewGezelModelAction());
      addAction(new OpenGezelModelAction());
      addAction(new OpenProjectAction());
      addAction(new CloseProjectAction());

      addAction(new NewTextFileAction());
      addAction(new OpenTextFileAction());
      addAction(new OpenFileAction());

      addAction(new NewVhdlFileAction());
      addAction(new OpenVhdlFileAction());

      addAction(new NewProjectAction());
      addAction(new SaveProjectAction());

      addAction(new ShowVersionHistoryAction());
      
      addAction(new SaveAllAction());
      addAction(new SaveSelectedItemAction());
      addAction(new SaveSelectedItemAsAction());
      addAction(new ShowSettingsAction());
      addAction(new ShowAboutAction());
      addAction(new CloseFileAction());

			addAction(new OpenRecentFileAction());
      addAction(new SelectNextOpenItemAction());
      addAction(new ExitApplicationAction());

			// gezel actions
			addAction(new InsertDatapathControllerUsingDialogAction());
			addAction(new InsertDatapathFsmSkeletonAction());
			addAction(new InsertDatapathHardwiredSkeletonAction());
			addAction(new InsertDatapathSequencerSkeletonAction());
      addAction(new InsertOpbSlaveIpBlockAction());
      addAction(new InsertMemoryIpBlock());
      addAction(new InsertSimplifiedOpbSlaveIpBlock());
      addAction(new ShowSynthesisOptionsAction());
      addAction(new InsertSimplifiedOpbMasterIpBlock());

      // MB cosim
      //addAction(new RunMicroblazeCosimulationAction());
      //addAction(new StopMicroblazeCosimulationAction());
      //addAction(new SetupMicroblazeCosimulationAction());

      // editing actions
      addAction(new GotoLineAction());

      // simulation actions
      addAction(new SimulateGezelModelAction());
      addAction(new RestartSimulationAction());
      addAction(new EndSimulationAction());

      addAction(new ParseAndVerifyGezelModelAction());

      addAction(new ShowOutputAction());
      addAction(new ShowErrorListAction());

      addAction(new ConvertToVhdlAction());
      //addAction(new SynthesizeAsOpbSlaveAction());
    }

    /// <summary>
    /// Helper method which registers an action.
    /// </summary>
    /// <param name="instance"></param>
    private static void addAction(ActionBase instance)
    {
      Type type = instance.GetType();
      System.Diagnostics.Debug.Assert(
        !actions.ContainsKey(type), 
        string.Format("action for type {0} is already registered!", type.Name)
      );
      actions[type] = instance;
    }

    public void BindToolStripItem(ToolStripItem item)
    {
      item.Enabled = this.enabled;
      item.Click += new EventHandler(Execute);
      boundItems.Add(item);
			OnItemBound(item);
    }

    public void UnbindMenuItem(ToolStripItem item)
    {
      item.Enabled = true;
      item.Click -= new EventHandler(Execute);
      boundItems.Remove(item);
    }

    public abstract void Execute(object sender, EventArgs e);
  }
}
